WebRTCç»é¢å ±æã®å®è£ ã«é¢ããå æ¬çãªã¬ã€ãããã¹ã¯ããããã£ããã£ãã¹ããªãŒãã³ã°æè¡ãã»ãã¥ãªãã£ãã°ããŒãã«ã¢ããªã±ãŒã·ã§ã³ã®ãã¹ããã©ã¯ãã£ã¹ã解説ã
ããã³ããšã³ãWebRTCç»é¢å ±æïŒã°ããŒãã«ã¢ããªã±ãŒã·ã§ã³ã®ããã®ãã¹ã¯ããããã£ããã£ãšã¹ããªãŒãã³ã°
Web Real-Time CommunicationïŒWebRTCïŒã¯ãWebäžã§ã®ãªã¢ã«ã¿ã€ã ã³ãã¥ãã±ãŒã·ã§ã³ã«é©åœãããããããã©ãŠã¶å ã§çŽæ¥ãã¢ããŒãã¢ã®é³å£°ããããªãããŒã¿è»¢éãå¯èœã«ããŸãããWebRTCã«ãã£ãŠå¯èœã«ãªãæãé åçãªæ©èœã®1ã€ãç»é¢å ±æã§ããããŠãŒã¶ãŒã¯ãªã¢ã«ã¿ã€ã ã§èªèº«ã®ãã¹ã¯ããããç¹å®ã®ã¢ããªã±ãŒã·ã§ã³ãŠã£ã³ããŠãå ±æã§ããŸãããã®æ©èœã¯ããªã³ã©ã€ã³äŒè°ããªã¢ãŒãã³ã©ãã¬ãŒã·ã§ã³ããã¯ãã«ã«ãµããŒããæè²ãã©ãããã©ãŒã ã«ãããŠéåžžã«äŸ¡å€ããããå°ççãªå¢çãè¶ããã·ãŒã ã¬ã¹ãªã³ãã¥ãã±ãŒã·ã§ã³ãä¿é²ããŸãããã®å æ¬çãªã¬ã€ãã§ã¯ãããã³ããšã³ãã§ã®WebRTCç»é¢å ±æã®å®è£ ã®è€éãªç¹ããã¹ã¯ããããã£ããã£ãšã¹ããªãŒãã³ã°æè¡ãã»ãã¥ãªãã£äžã®èæ ®äºé ããããŠå ç¢ã§ã°ããŒãã«ã«ã¢ã¯ã»ã¹å¯èœãªã¢ããªã±ãŒã·ã§ã³ãéçºããããã®ãã¹ããã©ã¯ãã£ã¹ã«çŠç¹ãåœãŠãŠæãäžããŸãã
WebRTCç»é¢å ±æã®çè§£
WebRTCç»é¢å
±æã¯ãgetUserMedia APIãå©çšããŠãŠãŒã¶ãŒã®ç»é¢ãç¹å®ã®ãŠã£ã³ããŠã«ã¢ã¯ã»ã¹ããŸãããã©ãŠã¶ã¯ãéžæããããœãŒã¹ããã®ãããªã¹ããªãŒã ããã£ããã£ããWebRTCã»ãã·ã§ã³ã®ä»ã®åå è
ã«éä¿¡ããŸãããã®ããã»ã¹ã«ã¯ããã€ãã®äž»èŠãªã¹ããããå«ãŸããŸãã
- ãŠãŒã¶ãŒéžæïŒ ãŠãŒã¶ãŒã¯ç»é¢å ±æããã»ã¹ãéå§ããå ±æãããç»é¢ãŸãã¯ãŠã£ã³ããŠãéžæããŸãã
- ã¹ããªãŒã ååŸïŒ
getUserMediaAPIã䜿çšããŠãéžæããããœãŒã¹ã衚ããããªã¹ããªãŒã ãååŸããŸãã - ãã¢æ¥ç¶ïŒ ãããªã¹ããªãŒã ã¯WebRTCãã¢æ¥ç¶ã«è¿œå ãããŸãã
- ã·ã°ããªã³ã°ïŒ ã·ã°ããªã³ã°ãµãŒããŒã¯ããã¢éã§SDPïŒSession Description ProtocolïŒãªãã¡ãŒãšã¢ã³ãµãŒã®äº€æãä¿é²ããæ¥ç¶ã確ç«ããŸãã
- ã¹ããªãŒãã³ã°ïŒ ãããªã¹ããªãŒã ã¯ããã¢ãããã¢ãžãšãªã¢ã«ã¿ã€ã ã§éä¿¡ãããŸãã
getDisplayMediaã«ãããã¹ã¯ããããã£ããã£ã®å®è£
ç»é¢å
±æå°çšã«èšèšãããgetUserMediaã®æ¡åŒµæ©èœã§ããgetDisplayMedia APIã¯ããã¹ã¯ããããã£ããã£ã®ããã»ã¹ãç°¡çŽ åããŸãããã®APIã¯ããŠãŒã¶ãŒã®ç»é¢ãŸãã¯ç¹å®ã®ã¢ããªã±ãŒã·ã§ã³ãŠã£ã³ããŠãžã®ã¢ã¯ã»ã¹ãèŠæ±ããããã®ãããæŽç·Žãããå®å
šãªæ¹æ³ãæäŸããŸããå€ããã»ãã¥ãªãã£ã®äœãæ¹æ³ã眮ãæãããŠãŒã¶ãŒã®ãã©ã€ãã·ãŒãšå¶åŸ¡ã匷åããŸãã
getDisplayMediaã®åºæ¬çãªäœ¿çšæ³
以äžã®ã³ãŒãã¹ããããã¯ãgetDisplayMediaã®åºæ¬çãªäœ¿çšæ³ã瀺ããŠããŸãã
async function startScreenShare() {
try {
const stream = await navigator.mediaDevices.getDisplayMedia({
video: true,
audio: true //ãªãã·ã§ã³ïŒç»é¢ããã®é³å£°ããã£ããã£ãããå Žå
});
//ã¹ããªãŒã ã®åŠçïŒäŸïŒãããªèŠçŽ ã«è¡šç€ºããïŒ
const videoElement = document.getElementById('screenShareVideo');
videoElement.srcObject = stream;
//ã¹ããªãŒã çµäºã®åŠç
stream.getVideoTracks()[0].addEventListener('ended', () => {
stopScreenShare(); //å
±æã忢ããããã®ã«ã¹ã¿ã 颿°
});
} catch (err) {
console.error('ç»é¢ãžã®ã¢ã¯ã»ã¹ãšã©ãŒïŒ', err);
//ãšã©ãŒåŠçïŒäŸïŒãŠãŒã¶ãŒãèš±å¯ãæåŠããå ŽåïŒ
}
}
function stopScreenShare() {
if (videoElement.srcObject) {
const stream = videoElement.srcObject;
const tracks = stream.getTracks();
tracks.forEach(track => track.stop());
videoElement.srcObject = null;
}
}
ãã®ã³ãŒãã¹ããããã¯ããŸãéåæé¢æ°startScreenShareãå®çŸ©ããŸãããã®é¢æ°å
ã§ãnavigator.mediaDevices.getDisplayMediaããç»é¢ããã®ãããªããã³ãªãã·ã§ã³ã§é³å£°ã®èŠæ±ã䌎ããªãã·ã§ã³ã§åŒã³åºããŸããè¿ãããã¹ããªãŒã ã¯ããã£ããã£ãããç»é¢ã衚瀺ããããã«videoèŠçŽ ã«å²ãåœãŠãããŸããã³ãŒãã«ã¯ããšã©ãŒåŠçãšãã¹ããªãŒã ãçµäºãããšãã«ç»é¢å
±æã忢ããã¡ã«ããºã ãå«ãŸããŠããŸããstopScreenShare颿°ã¯ãã¹ããªãŒã å
ã®ãã¹ãŠã®ãã©ãã¯ãé©åã«åæ¢ããŠãªãœãŒã¹ãè§£æŸããããã«å®è£
ãããŠããŸãã
getDisplayMediaã®èšå®ãªãã·ã§ã³
getDisplayMedia APIã¯ããªãã·ã§ã³ã®MediaStreamConstraintsãªããžã§ã¯ããåãå
¥ãããããªã¹ããªãŒã ã®ããŸããŸãªãªãã·ã§ã³ãæå®ã§ããŸãããããã®ãªãã·ã§ã³ã«ã¯ä»¥äžãå«ãŸããŸãã
videoïŒ ãããªã¹ããªãŒã ãèŠæ±ããããšã瀺ãããŒã«å€ïŒå¿ é ïŒãããã«å¶çŽãæå®ãããªããžã§ã¯ãã«ããããšãã§ããŸããaudioïŒ ãªãŒãã£ãªã¹ããªãŒã ãèŠæ±ããããšã瀺ãããŒã«å€ïŒãªãã·ã§ã³ïŒãã·ã¹ãã ãªãŒãã£ãªãŸãã¯ãã€ã¯ããã®ãªãŒãã£ãªããã£ããã£ããããã«äœ¿çšã§ããŸããpreferCurrentTabïŒ ïŒããŒã«å€ïŒçŸåšã®ã¿ããå ±æãªãã·ã§ã³ãšããŠãŠãŒã¶ãŒã«æåã«æäŸãããããã©ãŠã¶ã«ãã³ããäžããŸããïŒå®éšçïŒsurfaceSwitchingïŒ ïŒããŒã«å€ïŒãã£ããã£äžã«ãŠãŒã¶ãŒãå ±æãããŠãããµãŒãã§ã¹ãåãæ¿ããããšãèš±å¯ãããã©ããããã©ãŠã¶ã«ãã³ããäžããŸããïŒå®éšçïŒsystemAudioïŒ ïŒæååïŒã·ã¹ãã ãªãŒãã£ãªãå ±æãããã©ããã瀺ããŸãã蚱容ãããå€ã¯`"include"`ã`"exclude"`ã`"notAllowed"`ã§ããïŒå®éšçãã€ãã©ãŠã¶äŸåïŒ
ããå€ãã®ãªãã·ã§ã³ã䜿çšããäŸïŒ
async function startScreenShare() {
try {
const stream = await navigator.mediaDevices.getDisplayMedia({
video: {
cursor: "always", //ãŸã㯠"motion" ãŸã㯠"never"
displaySurface: "browser", //ãŸã㯠"window", "application", "monitor"
logicalSurface: true, //ç©çãµãŒãã§ã¹ã§ã¯ãªãè«çãµãŒãã§ã¹ãèæ
®ããŸãã
},
audio: true
});
//ã¹ããªãŒã ã®åŠçïŒäŸïŒãããªèŠçŽ ã«è¡šç€ºããïŒ
const videoElement = document.getElementById('screenShareVideo');
videoElement.srcObject = stream;
//ã¹ããªãŒã çµäºã®åŠç
stream.getVideoTracks()[0].addEventListener('ended', () => {
stopScreenShare(); //å
±æã忢ããããã®ã«ã¹ã¿ã 颿°
});
} catch (err) {
console.error('ç»é¢ãžã®ã¢ã¯ã»ã¹ãšã©ãŒïŒ', err);
//ãšã©ãŒåŠçïŒäŸïŒãŠãŒã¶ãŒãèš±å¯ãæåŠããå ŽåïŒ
}
}
ãŠãŒã¶ãŒæš©éã®åŠç
getDisplayMediaãåŒã³åºããšããã©ãŠã¶ã¯ãŠãŒã¶ãŒã«ç»é¢ãŸãã¯ãŠã£ã³ããŠã®å
±æãèš±å¯ããããããã³ããã衚瀺ããŸãããŠãŒã¶ãŒã®å¿çãé©åã«åŠçããããšãéèŠã§ãããŠãŒã¶ãŒãèš±å¯ãä»äžãããšãgetDisplayMediaã«ãã£ãŠè¿ããããããã¹ã¯MediaStreamãªããžã§ã¯ãã§è§£æ±ºãããŸãããŠãŒã¶ãŒãèš±å¯ãæåŠãããšããããã¹ã¯DOMExceptionã§æåŠãããŸãããŠãŒã¶ãŒãã¬ã³ããªãŒãªãšã¯ã¹ããªãšã³ã¹ãæäŸããããã«ãäž¡æ¹ã®ã·ããªãªãåŠçããŸããæš©éæåŠã®å Žåã¯ããŠãŒã¶ãŒã«æ
å ±ã¡ãã»ãŒãžã衚瀺ãããã©ãŠã¶ã®èšå®ã§ç»é¢å
±æãæå¹ã«ããæ¹æ³ãã¬ã€ãããŠãã ããã
getDisplayMediaã®ãã¹ããã©ã¯ãã£ã¹
- å¿ èŠãªæš©éã®ã¿ãèŠæ±ããïŒ ã¢ããªã±ãŒã·ã§ã³ã§çµ¶å¯Ÿã«å¿ èŠãšãããæš©éã®ã¿ãèŠæ±ããŠãã ãããããšãã°ãç¹å®ã®ã¢ããªã±ãŒã·ã§ã³ãŠã£ã³ããŠã®ã¿ãå ±æããå¿ èŠãããå Žåã¯ãç»é¢å šäœãžã®ã¢ã¯ã»ã¹ãèŠæ±ããªãã§ãã ãããããã«ããããŠãŒã¶ãŒã®ãã©ã€ãã·ãŒãšä¿¡é ŒãåäžããŸãã
- ãšã©ãŒãé©åã«åŠçããïŒ ãŠãŒã¶ãŒãæš©éãæåŠããå Žåãç»é¢å ±æãå©çšã§ããªãå Žåãé©åã«åŠçããããã«ãå ç¢ãªãšã©ãŒåŠçãå®è£ ããŸãã
- æç¢ºãªæç€ºãæäŸããïŒ ãŠãŒã¶ãŒãç»é¢å ±æã®æå¹åã«é¢ããŠåé¡ã«ééããå Žåããã©ãŠã¶ã§ç»é¢å ±æãæå¹ã«ããæ¹æ³ã«ã€ããŠãæç¢ºã§ç°¡æœãªæç€ºãæäŸããŸãã
- ãŠãŒã¶ãŒã®ãã©ã€ãã·ãŒãå°éããïŒ åžžã«ãŠãŒã¶ãŒã®ãã©ã€ãã·ãŒãå°éããç»é¢å ±æããã»ã¹ã«çŽæ¥é¢ä¿ã®ãªãæ©å¯æ å ±ããã£ããã£ãŸãã¯éä¿¡ããªãã§ãã ããã
ãã£ããã£ãããç»é¢ã®ã¹ããªãŒãã³ã°
ãã£ããã£ãããç»é¢ã衚ãMediaStreamãååŸãããããããWebRTCã»ãã·ã§ã³ã®ä»ã®åå è
ã«ã¹ããªãŒãã³ã°ã§ããŸããããã«ã¯ãã¹ããªãŒã ãWebRTCãã¢æ¥ç¶ã«è¿œå ãããªã¢ãŒããã¢ã«éä¿¡ããããšãå«ãŸããŸãã以äžã®ã³ãŒãã¹ããããã¯ãç»é¢å
±æã¹ããªãŒã ãæ¢åã®ãã¢æ¥ç¶ã«è¿œå ããæ¹æ³ã瀺ããŠããŸãã
async function addScreenShareToPeerConnection(peerConnection) {
try {
const stream = await navigator.mediaDevices.getDisplayMedia({
video: true,
audio: true
});
stream.getTracks().forEach(track => {
peerConnection.addTrack(track, stream);
});
return stream;
} catch (err) {
console.error('ãã¢æ¥ç¶ãžã®ç»é¢å
±æã®è¿œå ãšã©ãŒïŒ', err);
//ãšã©ãŒåŠç
return null;
}
}
ãã®äŸã§ã¯ãaddScreenShareToPeerConnection颿°ã¯RTCPeerConnectionãªããžã§ã¯ããå
¥åãšããŠåãåããŸããæ¬¡ã«ãgetDisplayMediaãåŒã³åºããŠç»é¢å
±æã¹ããªãŒã ãååŸããŸãããã®ã¹ããªãŒã ããã®ãã©ãã¯ã¯ãaddTrackã¡ãœããã䜿çšããŠãã¢æ¥ç¶ã«è¿œå ãããŸããããã«ãããç»é¢å
±æã¹ããªãŒã ããªã¢ãŒããã¢ã«éä¿¡ãããããšãä¿èšŒãããŸãã颿°ã¯ãå¿
èŠã«å¿ããŠåŸã§åæ¢ã§ããããã«ã¹ããªãŒã ãè¿ããŸãã
ã¹ããªãŒãã³ã°ããã©ãŒãã³ã¹ã®æé©å
ã¹ã ãŒãºã§å¿çæ§ã®é«ãç»é¢å ±æãšã¯ã¹ããªãšã³ã¹ã確ä¿ããã«ã¯ãã¹ããªãŒãã³ã°ããã©ãŒãã³ã¹ã®æé©åãäžå¯æ¬ ã§ããæ¬¡ã®ãã¯ããã¯ãæ€èšããŠãã ããã
- ã³ãŒããã¯éžæïŒ ç»é¢å ±æã¹ããªãŒã ã«é©ãããããªã³ãŒããã¯ãéžæããŸããVP8ãŸãã¯H.264ã®ãããªã³ãŒããã¯ã¯WebRTCã§äžè¬çã«äœ¿çšãããŸãããæé©ãªéžæã¯ç¹å®ã®ãŠãŒã¹ã±ãŒã¹ãšãã©ãŠã¶ã®ãµããŒãã«ãã£ãŠç°ãªããŸããSVCïŒScalable Video CodingïŒã³ãŒããã¯ã®äœ¿çšãæ€èšããŠãã ãããããã¯ããããã¯ãŒã¯æ¡ä»¶ã«åºã¥ããŠãããªå質ãåçã«èª¿æŽããŸãã
- è§£å床ãšãã¬ãŒã ã¬ãŒãïŒ ãããªå質ãšåž¯åå¹ æ¶è²»ã®ãã©ã³ã¹ããšãããã«ãç»é¢å ±æã¹ããªãŒã ã®è§£å床ãšãã¬ãŒã ã¬ãŒãã調æŽããŸããè§£å床ãŸãã¯ãã¬ãŒã ã¬ãŒããäžãããšãéä¿¡ãããããŒã¿ã®éãå€§å¹ ã«åæžãããå¯èœæ§ããããç¹ã«äœåž¯åå¹ ç°å¢ã§æçã§ãã
- 垯åå¹ æšå®ïŒ å©çšå¯èœãªåž¯åå¹ ã«åºã¥ããŠãããªå質ãåçã«èª¿æŽããããã«ã垯åå¹ æšå®æè¡ãå®è£ ããŸããWebRTCã¯ããããã¯ãŒã¯æ¡ä»¶ãç£èŠããã¹ããªãŒã ãã©ã¡ãŒã¿ãããã«å¿ããŠèª¿æŽããããã®APIãæäŸããŸãã
- RTPããããŒæ¡åŒµïŒ RTPïŒReal-time Transport ProtocolïŒããããŒæ¡åŒµã䜿çšããŠã空éçããã³æéçã¬ã€ã€ãŒãªã©ãã¹ããªãŒã ã«é¢ããè¿œå æ å ±ãæäŸããŸããããã¯ãã¢ãããã£ãã¹ããªãŒãã³ã°ã«äœ¿çšã§ããŸãã
- ã¹ããªãŒã ã®åªå
é äœä»ãïŒ
RTCRtpSender.setPriority()ã¡ãœããã䜿çšããŠããã¢æ¥ç¶å ã®ä»ã®ã¹ããªãŒã ãããç»é¢å ±æã¹ããªãŒã ãåªå ããååãªåž¯åå¹ ãåãåãããšãä¿èšŒããŸãã
ã»ãã¥ãªãã£äžã®èæ ®äºé
ç»é¢å ±æã«ã¯æ©å¯ããŒã¿ãå«ãŸãããããã»ãã¥ãªãã£äžã®èæ ®äºé ãæ éã«æ€èšããããšãéèŠã§ãããŠãŒã¶ãŒã®ãã©ã€ãã·ãŒãä¿è·ããäžæ£ã¢ã¯ã»ã¹ãé²ãããã«ã次ã®ã»ãã¥ãªãã£å¯Ÿçãå®è£ ããŠãã ããã
- HTTPSïŒ ã¯ã©ã€ã¢ã³ããšãµãŒããŒéã®éä¿¡ãæå·åããããã«ãåžžã«HTTPSçµç±ã§ã¢ããªã±ãŒã·ã§ã³ãæäŸããŠãã ãããããã«ãããçèŽãé²ããéä¿¡ãããããŒã¿ã®æŽåæ§ã確ä¿ããŸãã
- å®å šãªã·ã°ããªã³ã°ïŒ ãã¢éã§SDPãªãã¡ãŒãšã¢ã³ãµãŒã亀æããããã«ãå®å šãªã·ã°ããªã³ã°ã¡ã«ããºã ã䜿çšããŠãã ãããå®å šã§ãªããã£ãã«ã§ãã¬ãŒã³ããã¹ãã§æ©å¯æ å ±ãéä¿¡ããªãã§ãã ãããå®å šãªã·ã°ããªã³ã°ã«ã¯TLSæå·åãåããWebSocketsã®äœ¿çšãæ€èšããŠãã ããã
- èªèšŒãšèªå¯ïŒ ç»é¢å ±æã»ãã·ã§ã³ã«åå ã§ããã®ã¯ãæ£èŠã®ãŠãŒã¶ãŒã®ã¿ã§ããããšã確èªããããã«ãå ç¢ãªèªèšŒãšèªå¯ã¡ã«ããºã ãå®è£ ããŠãã ãããç»é¢å ±æã¹ããªãŒã ãžã®ã¢ã¯ã»ã¹ãä»äžããåã«ããŠãŒã¶ãŒã®IDã確èªããŠãã ããã
- ã³ã³ãã³ãã»ãã¥ãªãã£ããªã·ãŒïŒCSPïŒïŒ CSPããããŒã䜿çšããŠãã¢ããªã±ãŒã·ã§ã³ã«ãã£ãŠããŒãã§ããã³ã³ãã³ãã®ãœãŒã¹ãå¶éããŸããããã¯ãã¯ãã¹ãµã€ãã¹ã¯ãªããã£ã³ã°ïŒXSSïŒæ»æãé²ããã¢ããªã±ãŒã·ã§ã³ã«æªæã®ããã³ãŒããæ³šå ¥ããããªã¹ã¯ã軜æžããã®ã«åœ¹ç«ã¡ãŸãã
- ããŒã¿æå·åïŒ WebRTCã¯ãSRTPïŒSecure Real-time Transport ProtocolïŒã䜿çšããŠã¡ãã£ã¢ã¹ããªãŒã ãããã©ã«ãã§æå·åããŸããç»é¢å ±æã¹ããªãŒã ã®æ©å¯æ§ãä¿è·ããããã«ãSRTPãæå¹ã§æ£ããæ§æãããŠããããšã確èªããŠãã ããã
- 宿çãªæŽæ°ïŒ WebRTCã©ã€ãã©ãªãšãã©ãŠã¶ãææ°ã®ç¶æ ã«ä¿ã¡ãã»ãã¥ãªãã£è匱æ§ããããããŠãã ãããã»ãã¥ãªãã£ã¢ããã€ã¶ãªã宿çã«ç¢ºèªããææ°ã®ã¢ããããŒããéããã«é©çšããŠãã ããã
WebRTCç»é¢å ±æã®ã°ããŒãã«ãªèæ ®äºé
ã°ããŒãã«ãªãªãŒãã£ãšã³ã¹åãã®WebRTCç»é¢å ±æã¢ããªã±ãŒã·ã§ã³ãéçºããéã«ã¯ã次ã®èŠå ãèæ ®ããããšãäžå¯æ¬ ã§ãã
- ãããã¯ãŒã¯æ¡ä»¶ïŒ ãããã¯ãŒã¯æ¡ä»¶ã¯ãå°åã«ãã£ãŠå€§ããç°ãªããŸããããŸããŸãªåž¯åå¹ ãšã¬ã€ãã³ã·ãåŠçããããã«ã¢ããªã±ãŒã·ã§ã³ãæé©åããŠãã ããããããã¯ãŒã¯æ¡ä»¶ã«åºã¥ããŠãããªå質ã調æŽããããã«ãã¢ãããã£ãã¹ããªãŒãã³ã°æè¡ãå®è£ ããŠãã ãããNATãã©ããŒãµã«ãåŠçããããŸããŸãªå°åã§ã®æ¥ç¶æ§ã確ä¿ããããã«ãã°ããŒãã«ãªTURNãµãŒããŒãããã¯ãŒã¯ã䜿çšããŠãã ããã
- ãã©ãŠã¶ã®äºææ§ïŒ WebRTCã®ãµããŒãã¯ãããŸããŸãªãã©ãŠã¶ãããŒãžã§ã³ã«ãã£ãŠç°ãªããŸããäºææ§ãšäžè²«ãããŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ã確ä¿ããããã«ãããŸããŸãªãã©ãŠã¶ã§ã¢ããªã±ãŒã·ã§ã³ã培åºçã«ãã¹ãããŠãã ãããWebRTCã¢ããã¿ãŒã©ã€ãã©ãªã䜿çšããŠããã©ãŠã¶åºæã®éããæœè±¡åããéçºããã»ã¹ãç°¡çŽ åããŸãã
- ã¢ã¯ã»ã·ããªãã£ïŒ ç»é¢å ±æã¢ããªã±ãŒã·ã§ã³ãé害ã®ãããŠãŒã¶ãŒã«ãå©çšã§ããããã«ããŠãã ãããããŒããŒãããã²ãŒã·ã§ã³ãã¹ã¯ãªãŒã³ãªãŒããŒãµããŒããªã©ã®ä»£æ¿å ¥åæ¹æ³ãæäŸããŠãã ããããã¹ãŠã®ãŠãŒã¶ãŒã«ãšã£ãŠããŠãŒã¶ãŒã€ã³ã¿ãŒãã§ãŒã¹ãæç¢ºã§äœ¿ããããããšã確èªããŠãã ããã
- ããŒã«ã©ã€ãŒãŒã·ã§ã³ïŒ ããŸããŸãªèšèªãšå°åããµããŒãããããã«ãã¢ããªã±ãŒã·ã§ã³ãããŒã«ã©ã€ãºããŠãã ããããŠãŒã¶ãŒã€ã³ã¿ãŒãã§ãŒã¹ã翻蚳ããæåçã«é¢é£æ§ã®ããã³ã³ãã³ããæäŸããŠãã ãããããŒã«ã©ã€ãŒãŒã·ã§ã³ããã»ã¹ãåçåããããã«ã翻蚳管çã·ã¹ãã ã®äœ¿çšãæ€èšããŠãã ããã
- ã¿ã€ã ãŸãŒã³ïŒ ç»é¢å ±æã»ãã·ã§ã³ã®ã¹ã±ãžã¥ãŒã«èšå®ãšèª¿æŽã®éã«ã¯ãã¿ã€ã ãŸãŒã³ã®éããèæ ®ããŠãã ããããŠãŒã¶ãŒã«ããŒã«ã«ã¿ã€ã ãŸãŒã³ã§ã®ã»ãã·ã§ã³ãã¹ã±ãžã¥ãŒã«ããæ©èœãæäŸããæéããŠãŒã¶ãŒãã¬ã³ããªãŒãªåœ¢åŒã§è¡šç€ºããŸãã
- ããŒã¿ãã©ã€ãã·ãŒèŠå¶ïŒ ããŸããŸãªåœãå°åã®ããŒã¿ãã©ã€ãã·ãŒèŠå¶ãéµå®ããŠãã ãããå人ããŒã¿ãåéãŸãã¯åŠçããåã«ããŠãŒã¶ãŒããåæãåŸãŠãã ããããŠãŒã¶ãŒãã©ã€ãã·ãŒãä¿è·ããããã«ãé©åãªããŒã¿ã»ãã¥ãªãã£å¯Ÿçãå®è£ ããŠãã ãããããšãã°ããšãŒãããã®GDPRïŒGeneral Data Protection RegulationïŒã«ã¯ãããŒã¿ãã©ã€ãã·ãŒã«é¢ãã峿 ŒãªèŠä»¶ããããŸãã
é«åºŠãªãã¯ããã¯ãšèæ ®äºé
ä»®æ³èæ¯ãšãããªãšãã§ã¯ã
ä»®æ³èæ¯ãšãããªãšãã§ã¯ããçµã¿èŸŒãããšã§ãç»é¢å ±æãšã¯ã¹ããªãšã³ã¹ãåäžãããŸãããããã®æ©èœã¯ãç»é¢å ±æã¹ããªãŒã ã®èŠèŠçãªé åãåäžããããŠãŒã¶ãŒã«å€èŠãããå¶åŸ¡ã§ããããã«ããŸããTensorFlow.jsãMediapipeãªã©ã®JavaScriptã©ã€ãã©ãªã䜿çšããŠããããã®æ©èœãããã³ããšã³ãã§å¹ççã«å®è£ ããŸãã
é³å£°åŠçã䌎ãç»é¢å ±æ
ç»é¢å ±æã¹ããªãŒã ã®é³å£°å質ãåäžãããããã«ãé³å£°åŠçæè¡ãçµã¿èŸŒã¿ãŸããé³å£°åŠçã©ã€ãã©ãªã䜿çšããŠããã€ãºãäœæžãããšã³ãŒãæå¶ããé³å£°ã¬ãã«ãæ£èŠåããŸããããã«ãããé³å£°ã®æçããå€§å¹ ã«åäžããå šäœçãªã³ãã¥ãã±ãŒã·ã§ã³ãšã¯ã¹ããªãšã³ã¹ãåäžããŸãã
ã«ã¹ã¿ãã€ãºå¯èœãªç»é¢å ±æUI
ãŠãŒã¶ãŒã«ç»é¢å ±æãšã¯ã¹ããªãšã³ã¹ã®ããå€ãã®å¶åŸ¡ãæäŸããããã«ãã«ã¹ã¿ãã€ãºå¯èœãªç»é¢å ±æUIãäœæããŸãããŠãŒã¶ãŒãç»é¢ã®ç¹å®é åãéžæããŠå ±æããããç»é¢ã«æ³šéãä»ãããããããªå質ãå¶åŸ¡ãããã§ããããã«ããŸããããã«ããããŠãŒã¶ãŒãšã³ã²ãŒãžã¡ã³ããåäžããããããŒãœãã©ã€ãºãããç»é¢å ±æãšã¯ã¹ããªãšã³ã¹ãæäŸã§ããŸãã
ã³ã©ãã¬ãŒã·ã§ã³ãã©ãããã©ãŒã ãšã®çµ±å
SlackãMicrosoft TeamsãGoogle Meetãªã©ã®äžè¬çãªã³ã©ãã¬ãŒã·ã§ã³ãã©ãããã©ãŒã ãšWebRTCç»é¢å ±æãçµ±åããŸããããã«ããããŠãŒã¶ãŒã«ã·ãŒã ã¬ã¹ã§çµ±åãããã³ãã¥ãã±ãŒã·ã§ã³ãšã¯ã¹ããªãšã³ã¹ãæäŸã§ããŸãããã©ãããã©ãŒã ã®APIã䜿çšããŠãã³ã©ãã¬ãŒã·ã§ã³ãã©ãããã©ãŒã å ã§çŽæ¥ç»é¢å ±æãæå¹ã«ããŸãã
äŸïŒã·ã³ãã«ãªã°ããŒãã«ç»é¢å ±æã¢ããªã±ãŒã·ã§ã³
ã·ã³ãã«ãªã°ããŒãã«ç»é¢å ±æã¢ããªã±ãŒã·ã§ã³ã®æ§é ãæŠèª¬ããŸããããããã¯ãã€ã¬ãã«ãªäŸã§ããããã詳现ãªå®è£ ãå¿ èŠã§ãã
- ã·ã°ããªã³ã°ãµãŒããŒïŒ Socket.IOã䜿çšããNode.jsãµãŒããŒããªã¢ã«ã¿ã€ã éä¿¡ãåŠçããŸãããã®ãµãŒããŒã¯ããã¢éã®SDPãªãã¡ãŒãšã¢ã³ãµãŒã®äº€æãä¿é²ããŸãã
- ããã³ããšã³ãïŒHTMLãCSSãJavaScriptïŒïŒ HTMLãCSSãJavaScriptã䜿çšããŠæ§ç¯ããããŠãŒã¶ãŒã€ã³ã¿ãŒãã§ãŒã¹ããŠãŒã¶ãŒã€ã³ã¿ã©ã¯ã·ã§ã³ãç»é¢ãã£ããã£ãWebRTCãã¢æ¥ç¶ç®¡çãåŠçããŸãã
- TURNãµãŒããŒïŒ NATãã©ããŒãµã«ãåŠçããããŸããŸãªå°åã§ã®æ¥ç¶æ§ã確ä¿ããããã®ã°ããŒãã«ãªTURNãµãŒããŒãããã¯ãŒã¯ãXirsysãTwilioãªã©ã®ãµãŒãã¹ã¯ããã®ã€ã³ãã©ã¹ãã©ã¯ãã£ãæäŸã§ããŸãã
ããã³ããšã³ãJavaScriptã³ãŒãïŒå³è§£ïŒïŒ
//ç°¡ç¥åãããäŸ - æ¬çªç°å¢ã«ã¯é©ããŠããŸãã
const socket = io('https://your-signaling-server.com');
const peerConnection = new RTCPeerConnection();
async function startScreenShare() {
//...以åãšåæ§ã®getDisplayMediaã³ãŒã...
stream.getTracks().forEach(track => peerConnection.addTrack(track, stream));
//...ICEåè£ã®åŠçãã·ã°ããªã³ã°ãµãŒããŒçµç±ã®ãªãã¡ãŒ/ã¢ã³ãµãŒäº€æ...
}
//ICEåè£ã®åŠçã®äŸïŒç°¡ç¥åïŒ
peerConnection.onicecandidate = event => {
if (event.candidate) {
socket.emit('iceCandidate', event.candidate);
}
};
ãã®å³è§£çãªã³ãŒãã¯åºæ¬çãªæ§é ã瀺ããŠããŸããå®å šãªã¢ããªã±ãŒã·ã§ã³ã«ã¯ãå ç¢ãªãšã©ãŒåŠçãUIèŠçŽ ãããã³ãã詳现ãªã·ã°ããªã³ã°ããžãã¯ãå¿ èŠã§ãã
çµè«
WebRTCç»é¢å ±æã¯ãWebäžã§ã®ãªã¢ã«ã¿ã€ã ã³ã©ãã¬ãŒã·ã§ã³ãšã³ãã¥ãã±ãŒã·ã§ã³ãå¯èœã«ãã匷åãªãã¯ãããžãŒã§ãããã¹ã¯ããããã£ããã£ãã¹ããªãŒãã³ã°æè¡ãã»ãã¥ãªãã£äžã®èæ ®äºé ãããã³ã°ããŒãã«ãªèæ ®äºé ã®åºæ¬ãçè§£ããããšã§ããŠãŒã¶ãŒãå°ççãªå¢çãè¶ããŠå¹æçã«æ¥ç¶ããå ±åäœæ¥ã§ããããã«ãããå ç¢ã§ã°ããŒãã«ã«ã¢ã¯ã»ã¹å¯èœãªç»é¢å ±æã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ã§ããŸããWebRTCã®æè»æ§ãšãã¯ãŒã掻çšããŠãæ¥ç¶ãããäžçã®ããã®é©æ°çãªãœãªã¥ãŒã·ã§ã³ãäœæããŠãã ãããWebRTCãã¯ãããžãŒãé²åãç¶ããã«ã€ããŠãææ°ã®æ©èœãšãã¹ããã©ã¯ãã£ã¹ãææ¡ããŠããããšã¯ãæå 端ã®ã¢ããªã±ãŒã·ã§ã³ãéçºããããã«äžå¯æ¬ ã§ããSVCãªã©ã®é«åºŠãªãã¯ããã¯ãæ¢æ±ãããã©ãŠã¶åºæã®æé©åã調æ»ããã¢ããªã±ãŒã·ã§ã³ãç¶ç¶çã«ãã¹ãããŠãäžçäžã®ãŠãŒã¶ãŒã«ã·ãŒã ã¬ã¹ã§å®å šãªç»é¢å ±æãšã¯ã¹ããªãšã³ã¹ãæäŸããŠãã ããã